package com.zrz.service;

import com.google.common.collect.Maps;
import com.zrz.dao.auto.*;
import com.zrz.domain.ImageUpload;
import com.zrz.enums.RechargeEnum;
import com.zrz.model.auto.*;
import com.zrz.param.UserParam;
import com.zrz.resp.PreRechargeResp;
import com.zrz.util.*;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.w3c.dom.ls.LSException;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.sql.Struct;
import java.util.*;

@Service
public class UserService {
    @Value("${appId:wx35f41dbe47c47ad6}")
    private String appId;
    @Value("${secret:15b279674547279d2b2e6ad4a00aefe0}")
    private String secret;

    @Value("${money:299}")
    private BigDecimal money;
    @Value("${mallMoney:600}")
    private BigDecimal mallMoney;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RecordMapper recordMapper;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private RechargeMapper rechargeMapper;
    @Autowired
    private NideshopScoreMapper nideshopScoreMapper;
    @Autowired
    private NideshopShopScoreMapper nideshopShopScoreMapper;

    public User getUser(String code) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }
        WeiXinUtils weiXinUtils = new WeiXinUtils();
        User user = weiXinUtils.getUserInfo(code, appId, secret);
//         User user1=save(user);
        LogUtils.info("获取用户===" + user.getUnionid());
        return getUserInfoByOpenId(user, user.getOpenId());
    }

    public Object preRecharge(User user, String ip, Integer type) {

        LogUtils.debug("ip:" + ip);
        LogUtils.info("money===支付金额" + money);
        String tradeNo = ToolUtils.generateTradeNo();
        Recharge recharge = new Recharge();
        recharge.setUid(user.getId());
        recharge.setOpenId(user.getOpenId());


        recharge.setOutTradeNo(tradeNo);
        recharge.setStatus(RechargeEnum.NO_PAY.getCode());
        recharge.setType(type);
        rechargeMapper.insertSelective(recharge);
        String openId = user.getOpenId();
        HashMap<String, String> resultMap;
        if (type == 10) {
            recharge.setAmout(mallMoney);
            resultMap = WxUtils.unifiedOrder(openId, tradeNo, ip, mallMoney, String.format("用户：%d充值%s元", user.getId(), mallMoney), type);
        } else {
            recharge.setAmout(money);
            resultMap = WxUtils.unifiedOrder(openId, tradeNo, ip, money, String.format("用户：%d成为加盟商支付%s元", user.getId(), money), type);
        }
        LogUtils.info("预支付接口返回" + resultMap);
        if (resultMap == null) {
            //throw new CustomerException(CodeEnum.FAIL);
            recharge.setStatus(RechargeEnum.PAYERROR.getCode());
            rechargeMapper.updateByPrimaryKey(recharge);
        }
        String returnCode = resultMap.get("return_code");
        if (StringUtils.equalsIgnoreCase(returnCode, WxUtils.RETURN_CODE_FAIL)) {
            //throw new CustomerException(CodeEnum.FAIL, resultMap.get("return_msg"));
            recharge.setStatus(RechargeEnum.PAYERROR.getCode());
            rechargeMapper.updateByPrimaryKey(recharge);
        }

        String appId = WxUtils.APP_ID;
        String nonceStr = ToolUtils.randomStr(20);
        String timeStamp = String.valueOf(DateUtils.getCurrentMillsTime() / 1000);
        String packageStr = "prepay_id=" + resultMap.get("prepay_id");
        String signType = "MD5";

        TreeMap<String, String> dataMap = Maps.newTreeMap();
        dataMap.put("appId", appId);
        dataMap.put("nonceStr", nonceStr);
        dataMap.put("package", packageStr);
        dataMap.put("signType", signType);
        dataMap.put("timeStamp", timeStamp);
        String paySign = WxUtils.signByMd5(dataMap);
        PreRechargeResp resp = new PreRechargeResp();
        resp.setTimeStamp(timeStamp);
        resp.setNonceStr(nonceStr);
        resp.setPackageStr(packageStr);
        resp.setSignType(signType);
        resp.setPaySign(paySign);
        return resp;
    }

    public String rechargeNotify(HttpServletRequest request) {
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(request.getInputStream());
            HashMap<String, String> body = ToolUtils.xml2Map(document.asXML());
            LogUtils.info("支付返回body" + body);
            if (body == null) {
                return WxUtils.payRes(WxUtils.RETURN_CODE_FAIL, "请求数据错误");
            }
//            LogUtils.debug(body);
            String returnCode = body.get("return_code");
            String resultCode = body.get("result_code");
            String appid = body.get("appid");
            String mch_id = body.get("mch_id");
            String attach = "";
            if (body.containsKey("attach")) {
                attach = body.get("attach");
            }

            if (!StringUtils.equals(appid, WxUtils.APP_ID) || !StringUtils.equals(mch_id, WxUtils.MCH_ID)) {
//                throw new CustomerException(CodeEnum.OPERATE_FAIL, "非法来源");
            }
            if (StringUtils.equalsIgnoreCase(returnCode, WxUtils.RETURN_CODE_SUCCESS)) {
                if (StringUtils.equalsIgnoreCase(resultCode, WxUtils.RETURN_CODE_SUCCESS)) {
                    String tradeNo = body.get("out_trade_no");
                    String openId = body.get("openid");
                    String transactionId = body.get("transaction_id");
                    BigDecimal money = new BigDecimal(Long.parseLong(body.get("total_fee"))).divide(new BigDecimal(100));
                    if (attach.equalsIgnoreCase("10")) {
                        addMall(tradeNo);
                    } else {
                        this.recharge(tradeNo, openId, transactionId, money);
                    }

                }
            }
            return WxUtils.payRes(WxUtils.RETURN_CODE_SUCCESS, "OK");
        } catch (Exception e) {
            e.printStackTrace();
            return WxUtils.payRes(WxUtils.RETURN_CODE_FAIL, "请求数据错误");
        }
    }

    public Map getConfig(String url) {
        WeiXinUtils weiXinUtils = new WeiXinUtils();
        return weiXinUtils.getWxConfig(appId, secret, url);
    }

    public Map getUserByMobile(String mobile, Integer id) {
        Map map = new HashMap();
        if (id == null) {
            map.put("code", -1);
            map.put("msg", "请重新扫描商家二维码进行领酒操作！");
            return map;
        }
        UserExample userExample = new UserExample();
        userExample.createCriteria().andWineCodeEqualTo(mobile);
        List<User> userList = userMapper.selectByExample(userExample);
        if (userList.size() > 0) {
            map.put("code", 1);
        } else {
            map.put("code", -1);
            map.put("msg", "兑换码无效");
        }
        return map;
    }

    public User updateUser(UserParam userParam, User user) {
        user.setMobile(user.getMobile());
        user.setAddress(userParam.getAddress());
        user.setRealname(userParam.getRealname());
        user.setMobile(userParam.getMobile());
        if (!StringUtils.isEmpty(userParam.getMobile()) && user.getMember() && StringUtils.isEmpty(user.getWineCode())) {
            String mobile = userParam.getMobile();
            user.setWineCode(mobile.substring(mobile.length() - 4, mobile.length()) + getStr());
        }
        userMapper.updateByPrimaryKeySelective(user);
        return user;
    }

    public User getUserInfo(Integer id) {
        return userMapper.selectByPrimaryKey(id);
    }

    public List<User> getInvestUser(Integer id) {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andParentIdEqualTo(id);
        return userMapper.selectByExample(userExample);
    }

    public User getUserInfoByOpenId(User user, String openid) {
        LogUtils.info("开始检验用户unionid");
        UserExample userExample = new UserExample();
        userExample.createCriteria().andOpenIdEqualTo(openid);
        List<User> userList = userMapper.selectByExample(userExample);
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        User curUser = userList.get(0);
        if (user != null) {
            LogUtils.info("状态 ===" + StringUtils.isEmpty(curUser.getUnionid()));
            LogUtils.info("状态 ===" + StringUtils.isNotEmpty(user.getUnionid()));
            if (StringUtils.isEmpty(curUser.getUnionid()) && StringUtils.isNotEmpty(user.getUnionid())) {
                curUser.setUnionid(user.getUnionid());
                userMapper.updateByPrimaryKeySelective(curUser);
            }
        }
        return curUser;
    }

    public User getUserInfoByUnionId(String unionId) {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUnionidEqualTo(unionId);
        List<User> userList = userMapper.selectByExample(userExample);
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        return userList.get(0);
    }

    public User save(User user) {
        LogUtils.info("开始保存用户信息" + user);
        if (StringUtils.isNotBlank(user.getOpenId())) {
            UserExample userExample = new UserExample();
            userExample.createCriteria().andOpenIdEqualTo(user.getOpenId());
            List<User> users = userMapper.selectByExample(userExample);
            if (users.size() > 0) {
                return users.get(0);
            }
        }
        userMapper.insertSelective(user);
        LogUtils.info("保存数据完成");
        return user;
    }

    public Map getPayConfig(String url) {
        WeiXinUtils weiXinUtils = new WeiXinUtils();
        return weiXinUtils.getWxConfig("", "15b279674547279d2b2e6ad4a00aefe0", url);
    }


    public List<User> refferUser(Integer uid) {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andParentIdEqualTo(uid);
        return userMapper.selectByExample(userExample);
    }

    public List<Record> getRecord(Integer uid) {
        RecordExample recordExample = new RecordExample();
        recordExample.createCriteria().andUidEqualTo(uid);
        return recordMapper.selectByExample(recordExample);
    }

    public List<User> getAllUser() {
        UserExample userExample = new UserExample();
        userExample.createCriteria();
        return userMapper.selectByExample(userExample);
    }

    public User getUserById(Integer id) {
        return userMapper.selectByPrimaryKey(id);
    }

    public void update(User user) {
        User user1 = userMapper.selectByPrimaryKey(user.getId());
        user1.setRealname(user.getRealname());
        user1.setAddress(user.getAddress());
        user1.setMobile(user.getMobile());
        user1.setIdCard(user.getIdCard());
        userMapper.updateByPrimaryKeySelective(user1);
    }

    //获取已领取会员酒记录
    public List<Record> getLastRescord(Integer uid) {
        RecordExample recordExample = new RecordExample();
        recordExample.createCriteria().andUidEqualTo(uid);
        recordExample.setOrderByClause("'dead_line_date' desc");
        return recordMapper.selectByExample(recordExample);
    }

    //领取会员酒
    public Record insertWine(Integer uid, String openId, Integer type, Admin admin, Integer num) {
        Record record = new Record();
        record.setOpenId(openId);
        record.setUid(uid);
        record.setGetTime(new Date());
        record.setType(type);
        record.setBusId(admin.getId());
        record.setBusName(admin.getMallName());
        record.setNum(num);
        recordMapper.insert(record);
        User user = getUserInfo(uid);
        if (type == 1) {
            //会员酒数量减一
            user.setSurplusCount(user.getSurplusCount() - num);
            user.setLedSurplusCount(user.getLedExtensionCount() + num);

        } else {
            //推广酒数量减去
            user.setExtensionCount(user.getExtensionCount() - num);
            user.setLedExtensionCount(user.getExtensionCount() + num);
        }
        userMapper.updateByPrimaryKey(user);
        //更新商户
        admin.setYsNum(admin.getYsNum() + num);
        admin.setTotalNum(admin.getTotalNum() - num);
        adminMapper.updateByPrimaryKeySelective(admin);
        return record;
    }

    //领取酒
//    public Map  pickUpWine(Integer uid,Integer num,Integer busId,Integer type){
//        Map map=new HashMap();
//        map.put("code",1);
//        map.put("msg","领取成功");
//        User user = getUserInfo(uid);
//        //先判断领取数量 如果=1 则去先判断会员酒
//        //判断该会员有没有可以领取的酒  推广酒判断：查询user表中 推广酒数量(extension_count)与已领取推广酒数量(led_extension_count)的差
//        // 判断本月是否超出了会员期限 true 超出了 false 没超出
//        int extensionCount = getExtensionAvaNum(uid);//可领取推广酒数量
//        if(extensionCount<=0){
//            map.put("code",-1);
//            map.put("msg","推广酒数量不足");
//            return map;
//        }
//        if( !comparerDateMonth(new Date(),user.getDeadLineDate())){//没超出
//            List<Record> vipRecords = new ArrayList<>();
//            List<Record> records = getLastRescord(uid);//获取会员酒领取记录
//
//            for(int i =0;i<records.size();i++){
//                if(records.get(i).getType()==1){
//                    vipRecords.add(records.get(i));
//                }
//            }
//            if(vipRecords.size() >0){
//                if(comparerDateMonth(new Date(),vipRecords.get(0).getGetTime())){
//                    //可以领取会员酒
//                    if(num == 1){
//                        //领取会员酒
//                        insertWine(uid,user.getOpenId(),type,busId,1);
//                    }else{
//                        if(extensionCount >= num-1){
//                            //剩下的领取推广酒
//                            insertWine(uid,user.getOpenId(),type,busId,num-1);
//                        }else{
//                            map.put("code",-1);
//                            map.put("msg","推广酒数量不足");
//                        }
//                    }
//                }else{
//                    //本月已经领取了会员酒  领取推广酒
//                    //TODO 领取推广酒
//                    if(extensionCount>=num){
//                        insertWine(uid,user.getOpenId(),type,busId,num);
//                    }else{
//                        map.put("code",-1);
//                        map.put("msg","可领取数量不足");
//                    }
//                }
//            }else{
//                insertWine(uid,user.getOpenId(),type,busId,1);
//            }
//        }else{
//            //TODO 领取推广酒
//            if(extensionCount>=num){
//                insertWine(uid,user.getOpenId(),type,busId,num);
//            }else{
//                map.put("code",-1);
//                map.put("msg","可领取数量不足");
//            }
//        }
//        return map;
//    }
    //领取酒
    public Map pickUpWine(Integer uid, Integer num, Admin admin, Integer type) {
        User user = getUserById(uid);
        Map map = new HashMap();
        map.put("code", 1);
        map.put("msg", "领取成功");
        if (!user.getMember()) {
            map.put("code", -1);
            map.put("msg", "请开通会员！");
            return map;
        }
        if ((admin.getTotalNum() - admin.getYsNum()) < num) {
            map.put("code", -1);
            map.put("msg", "商户库存不足");
            return map;
        }
        if (user.getMember()) {
            if (type == 1) {//会员酒
                if (user.getSurplusCount() < num) {
                    map.put("code", -1);
                    map.put("msg", "会员酒剩余量不足");
                    return map;
                }
                List<Record> records = getLastRescord(uid);//获取会员酒领取记录
                if (records.size() > 0) {
                    Record record = records.get(0);
                    if (DateUtils.getDateBySimplDate(record.getGetTime(), "yyyy-MM").equals(DateUtils.getDateBySimplDate(new Date(), "yyyy-MM"))) {//本月已领取
                        map.put("code", -1);
                        map.put("msg", "本月已领取");
                        return map;
                    }
                    insertWine(uid, user.getOpenId(), type, admin, num);

                } else {
                    insertWine(uid, user.getOpenId(), type, admin, num);
                }
            } else if (type == 2) {
                if (user.getExtensionCount() < num) {
                    map.put("code", -1);
                    map.put("msg", "推广酒数量不足");
                    return map;
                }

                insertWine(uid, user.getOpenId(), type, admin, num);
            }
        } else {
            map.put("code", -1);
            map.put("msg", "会员已到期");
        }
        return map;
    }


    //获取可领取的推广酒数量
    private Integer getExtensionAvaNum(Integer uid) {
        User user = getUserInfo(uid);
        int count = user.getExtensionCount() - user.getLedExtensionCount();
        return count;
    }

    private boolean comparerDateMonth(Date now, Date deadline) {
        int a = now.getMonth() + now.getYear() * 1000;
        int b = deadline.getMonth() + deadline.getYear() * 1000;
        if (a > b) {
            return true;
        } else {
            return false;
        }
    }


    private String recharge(String tradeNo, String openId, String transactionId, BigDecimal money) {
        RechargeExample rechargeExample = new RechargeExample();
        rechargeExample.createCriteria().andOutTradeNoEqualTo(tradeNo);
        List<Recharge> rechargeList = rechargeMapper.selectByExample(rechargeExample);
        if (CollectionUtils.isEmpty(rechargeList)) {
            return WxUtils.payRes(WxUtils.RETURN_CODE_FAIL, "订单不存在");
        }
        Recharge recharge = rechargeList.get(0);
        recharge.setStatus(1);
        recharge.setUpdateTime(new Date());
        rechargeMapper.updateByPrimaryKey(recharge);

        //更新用户表
        User user = userMapper.selectByPrimaryKey(recharge.getUid());
        user.setStartMonth(recharge.getType());
        activityUser(user, null);
        if (user.getParentId() != null) {
            User referUser = userMapper.selectByPrimaryKey(user.getParentId());
            referUser.setExtensionCount(referUser.getExtensionCount() + 1);
            referUser.setTotalCount(referUser.getTotalCount() + 1);
            userMapper.updateByPrimaryKey(referUser);
        }

        //送积分
        giveScore(user, recharge);
        return WxUtils.payRes(WxUtils.RETURN_CODE_SUCCESS, "处理成功");

    }

    public void activityUser(User user, Redcode redcode) {
        if (redcode == null) {
            user.setTotalCount(user.getTotalCount() + 6);
            user.setSurplusCount(user.getSurplusCount() + 6);
        } else {
            user.setTotalCount(user.getTotalCount() + redcode.getCount());
            user.setSurplusCount(user.getSurplusCount() + redcode.getCount());
        }

        user.setMember(true);
        user.setDeadLineDate(DateUtils.addYear(1));
        user.setStartDate(new Date());
        if (StringUtils.isNotEmpty(user.getMobile())) {
            int length = user.getMobile().length();
            user.setWineCode(user.getMobile().substring(length - 4, length) + getStr());
        }
        userMapper.updateByPrimaryKeySelective(user);
    }

    private String getStr() {
        return RandomStringUtils.randomAlphabetic(2);
    }

    public ImageUpload imageUpload(String url) {
        ImageUpload imageUpload = UploadImageUitl.uploadTempMediaByUrl(appId, secret, url);
        return imageUpload;
    }

    private void giveScore(User user, Recharge recharge) {
        NideshopScoreExample nideshopScoreExample = new NideshopScoreExample();
        nideshopScoreExample.createCriteria().andUserIdEqualTo(user.getId());
        List<NideshopScore> nideshopShopScores = nideshopScoreMapper.selectByExample(nideshopScoreExample);
        if (CollectionUtils.isEmpty(nideshopShopScores)) {
            NideshopScore nideshopScore = new NideshopScore();
            nideshopScore.setUserId(user.getId());
            nideshopScore.setTotalScore(recharge.getAmout().intValue());
            nideshopScoreMapper.insertSelective(nideshopScore);
        } else {
            NideshopScore nideshopScore = nideshopShopScores.get(0);
            nideshopScore.setTotalScore(nideshopScore.getTotalScore() + recharge.getAmout().intValue());
            nideshopScoreMapper.updateByPrimaryKeySelective(nideshopScore);
        }
        //插入获取积分记录
        NideshopShopScore shopScore = new NideshopShopScore();
        shopScore.setUserId(user.getId());
        shopScore.setScore(recharge.getAmout().intValue());
        shopScore.setGetTime(new Date());
        shopScore.setGetType(40);
        shopScore.setRemark("用户微信充值赠送积分！");
        shopScore.setStatus(1);
        nideshopShopScoreMapper.insertSelective(shopScore);
    }

    public int addUserUnionId() {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUnionidIsNull();
        List<User> userList = userMapper.selectByExample(userExample);
        int count = 0;
        for (int i = 0; i < userList.size(); i++) {
            User user = userList.get(i);
            WeiXinUtils weiXinUtils = new WeiXinUtils();
            String unionId = weiXinUtils.getUserInfoByOpenid(user.getOpenId(), appId, secret);
            if (StringUtils.isNotEmpty(unionId)) {
                user.setUnionid(unionId);
                userMapper.updateByPrimaryKeySelective(user);
                count++;
            }
        }
        return count;
    }

    public void updateByPrimaryKeySelective(User user) {
        userMapper.updateByPrimaryKeySelective(user);
    }


    private String addMall(String tradeNo) {
        RechargeExample rechargeExample = new RechargeExample();
        rechargeExample.createCriteria().andOutTradeNoEqualTo(tradeNo);
        List<Recharge> rechargeList = rechargeMapper.selectByExample(rechargeExample);
        if (CollectionUtils.isEmpty(rechargeList)) {
            return WxUtils.payRes(WxUtils.RETURN_CODE_FAIL, "订单不存在");
        }
        Recharge recharge = rechargeList.get(0);
        recharge.setStatus(1);
        recharge.setUpdateTime(new Date());
        rechargeMapper.updateByPrimaryKey(recharge);

        //更新用户表
        User user = userMapper.selectByPrimaryKey(recharge.getUid());
        AdminExample example = new AdminExample();
        example.createCriteria().andUidEqualTo(user.getId());
        Admin admin = adminMapper.selectByExample(example).stream().findFirst().orElse(null);
        if (admin != null) {
            admin.setStatus(1);
            adminMapper.updateByPrimaryKeySelective(admin);
        }
        return WxUtils.payRes(WxUtils.RETURN_CODE_SUCCESS, "处理成功");

    }
}
